package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zzyl.base.PageBean;
import com.zzyl.dto.UserDto;
import com.zzyl.entity.*;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.*;
import com.zzyl.properties.SecurityProperties;
import com.zzyl.service.UserService;
import com.zzyl.utils.NoProcessing;
import com.zzyl.utils.ThreadLocalUtil;
import com.zzyl.vo.UserVo;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 用户表服务实现类
 */
@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {

    final UserMapper userMapper;
    final RoleMapper roleMapper;
    final DeptMapper deptMapper;
    final PostMapper postMapper;
    final UserRoleMapper userRoleMapper;
    final SecurityProperties securityProperties;

    /**
     * 分页条件查询
     *
     * @param pageNum
     * @param pageSize
     * @param dto
     * @return
     */
    @Override
    public PageBean<UserVo> pageQuery(Integer pageNum, Integer pageSize, UserDto dto) {
        //开启分页
        PageHelper.startPage(pageNum, pageSize);
        //处理部门编号，提取部门的有效前缀，SQL会模糊查询部门比编号
        String deptNo = NoProcessing.processString(dto.getDeptNo()); //100001000000000 -> 100001
        dto.setDeptNo(deptNo);

        //////////////////////////////////////////一个用户对应一个部门
        //////////////////////////////////////////一个用户对应一个职位
        Page<User> page = userMapper.selectPage(dto);
        PageBean<UserVo> pageBean = PageBean.of(page, UserVo.class);

        //////////////////////////////////////////一个用户对应多个角色
        pageBean.getRecords().forEach(userVo -> {
            //创建UserVo对象 = User信息 + List角色信息

            //查询用户的角色集合
            List<Role> roleList = roleMapper.findRoleListByUserId(userVo.getId());

            //提取  List<Role> 中的每一个角色的id
            List<String> roleIds = CollUtil.getFieldValues(roleList, "id", String.class);
            //提取  List<Role> 中的每一个角色的名称
            List<String> roleNames = CollUtil.getFieldValues(roleList, "roleName", String.class);

            //将处理之后角色信息封装到UserVo中（UserVo信息就已经补全完毕）
            userVo.setRoleVoIds(Set.copyOf(roleIds));
            userVo.setRoleLabels(Set.copyOf(roleNames));
        });

        return pageBean;
    }

    @Override
    @Transactional
    public void createUser(UserDto userDto) {
        //根据部门编号查询，是否是最底层的部门，如果不是，不允许添加用户
        int count = deptMapper.isLowestDept(userDto.getDeptNo());
        if (count > 0) {
            throw new BaseException(BasicEnum.USER_LOCATED_BOTTOMED_DEPT);
        }

        //转换UserVo为User
        User user = BeanUtil.toBean(userDto, User.class);
        user.setUsername(user.getEmail());
        user.setNickName(user.getRealName());
        user.setDataState("0");//0正常 1停用
        //TODO 需要设置默认，并且需要加密
        String password = DigestUtil.bcrypt(securityProperties.getDefaultPassword());
        user.setPassword(password);

        userMapper.insert(user);

        //保存用户角色中间表
        userDto.getRoleVoIds().forEach(roleId -> {
            UserRole userRole = UserRole.builder()
                    .userId(user.getId())
                    .roleId(Long.valueOf(roleId))
                    .dataState("0")
                    .build();
            userRoleMapper.insert(userRole);
        });
    }


    @Override
    @Transactional
    public void updateUser(UserDto userDto) {
        //根据部门编号查询，是否是最底层的部门，如果不是，不允许添加用户
        int count = deptMapper.isLowestDept(userDto.getDeptNo());
        if (count > 0) {
            throw new BaseException(BasicEnum.USER_LOCATED_BOTTOMED_DEPT);
        }

        //转换UserVo为User
        User user = BeanUtil.toBean(userDto, User.class);
        user.setUsername(userDto.getEmail());
        userMapper.updateByPrimaryKeySelective(user);

        if (CollUtil.isEmpty(userDto.getRoleVoIds())) {
            return;
        }

        //删除角色中间表
        userRoleMapper.deleteUserRoleByUserId(user.getId());
        //重新保存角色中间表
        userDto.getRoleVoIds().forEach(roleId -> {
            UserRole userRole = UserRole.builder()
                    .userId(user.getId())
                    .roleId(Long.valueOf(roleId))
                    .dataState("0")
                    .build();
            userRoleMapper.insert(userRole);
        });
    }


    @Override
    public void deleteUserById(Long userId) {
        // 删除用户与角色关联
        userRoleMapper.deleteUserRoleByUserId(userId);
        // 删除用户与岗位关联
        userMapper.deleteByPrimaryKey(userId);
    }

    /**
     * 启用或禁用用户
     */
    @Override
    public void isEnable(Long id, String status) {
        User user = User.builder()
                .id(id)
                .dataState(status)
                .build();
        userMapper.updateByPrimaryKeySelective(user);
    }

    /**
     * 多条件查询用户表列表
     */
    @Override
    public List<UserVo> findUserList(UserDto userDto) {
        List<User> userList = userMapper.selectList();
        return BeanUtil.copyToList(userList, UserVo.class);
    }

    /**
     * 重置密码
     *
     * @param userId
     * @return
     */
    @Override
    public void resetPasswords(Long userId) {
        String password = DigestUtil.bcrypt(securityProperties.getDefaultPassword());
        User user = User.builder()
                .password(password)
                .id(userId)
                .build();
        userMapper.updateByPrimaryKeySelective(user);
    }

    /**
     * 获取个人信息
     *
     * @return
     */
    @Override
    public UserVo getCurrentUser() {
        Long id = ThreadLocalUtil.get();
        User user = userMapper.selectByPrimaryKey(id);
        UserVo userVo = BeanUtil.toBean(user, UserVo.class);

        List<Role> roleList = roleMapper.findRoleListByUserId(userVo.getId());
        Set<String> roleNames = roleList.stream().map(role -> role.getRoleName()).collect(Collectors.toSet());
        userVo.setRoleNames(roleNames);

        Dept dept = deptMapper.selectByDeptNo(user.getDeptNo());
        userVo.setDeptName(dept.getDeptName());

        Post post = postMapper.selectByPostNo(user.getPostNo());
        userVo.setPostName(post.getPostName());

        return userVo;
    }
}
